document.getElementById('startBtn').addEventListener('click', function() {
    Engine.getInstance().start();
});
document.getElementById('stopBtn').addEventListener('click', function() {
    Engine.getInstance().stop();
});

log();


/**
 * @class Engine
 */

function Engine() {

    const statusEmbu = ['STOP', 'DOING', 'DONE', 'ERROR'];
    var status = statusEmbu[2];
    var compile = new Compile({
        callback: function(status, id) {
            console.log(status, this);
            switch (status) {
                case 'START':
                    changeStatus(1);
                    break;
                case 'STOP':
                default:
                    changeStatus(3);
                    break;
            }
        }
    });

    /**
     * @inner
     * @return {string} 返回一个当前的状态值
     */
    function getStatus() {
        return status;
    }

    /**
     * 
     */
    this.start = function() {
        if (runCheck()) {
            changeStatus(1);
            console.log('开始编译');
            compile.start();
        } else {
            console.log('正在编译中，请稍后再试');
        }
    }

    this.stop = function() {
        if (getStatus() === 'DOING') {
            console.log('停止编译');
            compile.stop()
        }
    }

    /**
     * 
     * @inner
     * @returns {boolean} 返回可否运行
     */
    function runCheck() {
        return getStatus() !== 'DOING';
    }

    /**
     * 
     * @inner
     * @param {number} statusCode 运行状态码
     */
    function changeStatus(statusCode) {
        statusCode = !isNaN(statusCode) && statusCode || 3;
        status = statusEmbu[statusCode] || statusEmbu[3];
    }

}

/**
 * 
 * @returns {object} 返回一个引擎单例对象
 */
Engine.getInstance = function() {
    if (!Engine.instance) {
        Engine.instance = new Engine();
    }
    return Engine.instance;
}

function Compile(opts) {
    var that = this;
    this.compileId = null;
    this.callback = opts && opts.callback;

    this.start = function() {
        if (this.compileId) {
            clearInterval(this.compileId);
        }

        this.compileId = setInterval(function() {
            console.log(1);
        }, 1000);

        runCallback(that.callback, ['START', this.compileId], that);

        // delay(5000).then(function() {
        //     //这里的延时器异步有问题，这边只是简单的控制调用停止函数，具体的问题表现为短时（开始到停止时间短于延迟时间）的时候会出现停止失灵
        //     //因为这里只是用延迟模拟编译器的结束回掉，实际的回调函数不会出现这种问题，所以此问题忽略
        //     that.compileId && that.stop();
        // });

        (function() {

            //通过闭包这边解决上边代码中的问题

            var curId = that.compileId;
            delay(5000).then(() => {
                that.compileId && that.compileId === curId && that.stop();
                curId = null;
            });

        }());

    }
    this.stop = function() {
        clearInterval(this.compileId);

        runCallback(that.callback, ['STOP', this.compileId], that);

        this.compileId = null;

    }
}

/**-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 * 工具函数
 * ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */

/**
 * 
 * @param {number} time 延迟的时间ms
 * @returns {promise} 一个延迟promise
 */
function delay(time) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, time);
    })
};

/**
 * 
 * @param {function} fn 回调函数
 * @param {array=} args   参数数组
 * @param {object=} context 上下文对象，默认值为window
 */
function runCallback(fn, args = [], context = window) {
    typeof fn === 'function' && fn.apply(context, args);
}

/**
 * 
 * @function log
 * @name log
 */
function log() {
    var _log = console.log;
    console.log = function(...param) {
        _log.apply(null, ['[[输出]]', (new Date), '=>>>>>>', ...param]);
    }
}